package com.gitee.dfdiot.sdk.utils.request;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.*;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


public class HttpClientUtil {

    //private static Logger LOGGER = LoggerFactory.getLogger(HttpClientUtil.class);

    private RequestConfig requestConfig = RequestConfig.custom()
            .setSocketTimeout(8000)
            .setConnectTimeout(8000)
            .setConnectionRequestTimeout(8000)
            .build();

    private static HttpClientUtil instance = null;

    private HttpClientUtil() {
    }

    public static HttpClientUtil getInstance() {
        if (instance == null) {
            instance = new HttpClientUtil();
        }
        return instance;
    }


    /**
     * Get请求
     *
     * @param httpUrl 请求路径
     * @param params  参数Map集合
     * @return String
     */
    public String doGet(String httpUrl, Map<String, String> params) {
        HttpGet httpGet = null;
        try {
            URIBuilder uriBuilder = new URIBuilder(httpUrl);
            if (null != params) {
                for (String key : params.keySet()) {
                    uriBuilder.addParameter(key, params.get(key));
                }
            }
            URI uri = uriBuilder.build();
            httpGet = new HttpGet(uri);
        } catch (Exception e) {
        }
        return sendHttpGet(httpGet);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param maps    参数
     */
    public String doPost(String httpUrl, Map<String, String> maps) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            StringEntity stringEntity = new UrlEncodedFormEntity(nameValuePairs, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpUrl={},maps={}", httpUrl, maps, e);
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param maps    参数
     */
    public String doPut(String httpUrl, Map<String, String> maps) {
        HttpPut httpPut = new HttpPut(httpUrl);// 创建httpPost
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            StringEntity stringEntity = new UrlEncodedFormEntity(nameValuePairs, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");
            httpPut.setEntity(stringEntity);
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpUrl={},maps={}", httpUrl, maps, e);
        }
        return sendHttpPut(httpPut);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param params  参数
     */
    public String doDelete(String httpUrl, Map<String, String> params) {
        HttpDelete httpDelete = new HttpDelete(httpUrl);// 创建httpPost
        // 创建参数队列
        try {

            URIBuilder uriBuilder = new URIBuilder(httpUrl);
            if (null != params) {
                for (String key : params.keySet()) {
                    uriBuilder.addParameter(key, params.get(key));
                }
            }
            URI uri = uriBuilder.build();
            httpDelete.setURI(uri);
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpUrl={},maps={}", httpUrl, maps, e);
        }
        return sendHttpDelete(httpDelete);
    }


    /**
     * 发送Post请求
     *
     * @param httpPost
     * @return
     */
    private String sendHttpPost(HttpPost httpPost) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPost);

            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            //System.out.println("响应状态码===:::"+statusCode);
            if (statusCode != 200) {
                return "fail";
            }
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpPost={}", httpPost, e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                //LOGGER.error("释放资源异常", e);
            }
        }
        return responseContent;
    }

    /**
     * 发送Put请求
     *
     * @param httpPut
     * @return
     */
    private String sendHttpPut(HttpPut httpPut) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpPut.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPut);

            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            //System.out.println("响应状态码===:::"+statusCode);
            if (statusCode != 200) {
                return "fail";
            }
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpPost={}", httpPost, e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                //LOGGER.error("释放资源异常", e);
            }
        }
        return responseContent;
    }


    /**
     * 发送Get请求
     *
     * @param httpGet
     * @return
     */
    private String sendHttpGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpGet={}", httpGet, e);
        } finally {
            try {
                // 关闭连接,
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                // LOGGER.error("释放资源异常", e);
            }
        }
        return responseContent;
    }


    /**
     * 发送Get请求
     *
     * @param httpDelete
     * @return
     */
    private String sendHttpDelete(HttpDelete httpDelete) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpDelete.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpDelete);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpGet={}", httpGet, e);
        } finally {
            try {
                // 关闭连接,
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                // LOGGER.error("释放资源异常", e);
            }
        }
        return responseContent;
    }

    /**
     * 发送Get请求Https
     *
     * @param httpGet
     * @return
     */
    private String sendHttpsGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
            DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
            httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpGet={}", httpGet, e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                //LOGGER.error("释放资源异常", e);
            }
        }
        return responseContent;
    }


    /**
     * 发送json格式的post请求
     *
     * @param jsonParam
     * @param urls
     * @return
     */
    public static String getJsonData(JSONObject jsonParam, String urls) {
        try {
            //创建连接
            URL url = new URL(urls);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestProperty("Content-Type", "application/json");
            connection.connect();
            //POST请求
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            /*JSONObject obj = new JSONObject();
			obj.element("app_name", "asdf");
			obj.element("app_ip", "10.21.243.234");
			obj.element("app_port", 8080);
			obj.element("app_type", "001");
			obj.element("app_area", "asd");*/

            out.writeBytes(jsonParam.toString());
            out.flush();
            out.close();

            //读取响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String lines;
            StringBuffer sb = new StringBuffer("");
            while ((lines = reader.readLine()) != null) {
                lines = new String(lines.getBytes(), "utf-8");
                sb.append(lines);
            }
            System.out.println(connection.getResponseCode() + "------------" + sb);
            reader.close();
            // 断开连接
            connection.disconnect();
            return sb.toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 发送HTTP post方式请求
     *
     * @param httpServerUrl 请求地址
     * @param reqBody       请求的body字符串
     * @return
     */
    public static String sendHttpPostReqToServerByReqbody(String httpServerUrl, String reqBody, String contentType) {
        if (null == httpServerUrl || httpServerUrl == "")
            return null;
        if (null == contentType || contentType == "")
            contentType = "application/x-www-form-urlencoded";
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String result = null;
        String status = null;
        try {
            HttpPost httpPost = new HttpPost(httpServerUrl);
            if (null != reqBody && reqBody != "") {
                StringEntity reqBodyEntity = new StringEntity(reqBody, StandardCharsets.UTF_8);
                reqBodyEntity.setContentType(contentType);
                httpPost.setEntity(reqBodyEntity);
            }
            CloseableHttpResponse response1 = httpclient.execute(httpPost);
            try {
                if (null != response1) {
                    if (null != response1.getStatusLine())
                        status = response1.getStatusLine().toString();
                    if (null != response1.getEntity())
                        result = EntityUtils.toString(response1.getEntity(), StandardCharsets.UTF_8);
                }
            } catch (ParseException e) {
                //LOGGER.error("向Http服务端发送请求时发生异常，原因：", e);
            } finally {
                if (response1 != null)
                    response1.close();
            }
        } catch (IOException e) {
            //LOGGER.error("向Http服务端发送请求时发生异常，原因：", e);
        } finally {
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    //LOGGER.error("关闭httpclient时发生异常，原因：", e);
                }
            }
        }
        //LOGGER.info(String.format("向Http服务端发送请求，请求地址：%s，请求报文：%s，请求返回状态：%s，请求返回报文：%s", httpServerUrl, reqBody, status, result));
        return result;
    }

    /**
     * 上传multipart
     *
     * @param httpUrl
     * @param headers
     * @param params
     * @param file
     * @return
     */
    public static String uploadFile(String httpUrl, Map<String, String> headers, Map<String, String> params, File file) {
        HttpPost httpPost = new HttpPost(httpUrl);
//        RequestConfig requestConfig =  RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
//        httpPost.setConfig(requestConfig);
        String result = null;
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();

            // 配置消息头
            Iterator headerIterator = headers.entrySet().iterator();          //循环增加header
            while (headerIterator.hasNext()) {
                Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIterator.next();
                httpPost.addHeader(elem.getKey(), elem.getValue());
            }

            // 配置消息体
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            multipartEntityBuilder.addBinaryBody("file", file);
            if (null != params && !params.isEmpty()) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue());
                }
            }
            HttpEntity httpEntity = multipartEntityBuilder.build();
            httpPost.setEntity(httpEntity);

            // 发送请求
            CloseableHttpResponse response1 = httpclient.execute(httpPost);
            try {
                if (null != response1) {
                    if (null != response1.getEntity())
                        result = EntityUtils.toString(response1.getEntity(), StandardCharsets.UTF_8);
                }
            } catch (ParseException e) {
                //LOGGER.error("向Http服务端发送请求时发生异常，原因：", e);
            } finally {
                if (response1 != null)
                    response1.close();
            }
        } catch (Exception e) {
            //LOGGER.error("向Http服务端发送请求时发生异常，原因：", e);
        }
        return result;

    }

    /**
     * 发送 POST 请求（HTTP），JSON形式
     *
     * @param httpUrl
     * @param json    json对象
     * @return
     */
    public String doPost(String httpUrl, Object json) {
        HttpPost httpPost = new HttpPost(httpUrl);
        CloseableHttpResponse response = null;

        try {
            httpPost.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");//解决中文乱码问题
            //stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpUrl={},json={}", httpUrl, json, e);
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    //LOGGER.error("请求异常,httpUrl={},json={}", httpUrl, json, e);
                }
            }
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param params  参数(格式:key1=value1&key2=value2)
     */
    public String sendHttpPost(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            //LOGGER.error("请求异常httpUrl={},param={}", httpUrl, params, e);
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 get请求Https
     *
     * @param httpUrl
     */
    public String sendHttpsGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpsGet(httpGet);
    }

    /**
     * 发送 post请求（带文件）
     *
     * @param httpUrl   地址
     * @param maps      参数
     * @param fileLists 附件
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps, List<File> fileLists) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();
        for (String key : maps.keySet()) {
            meBuilder.addPart(key, new StringBody(maps.get(key), ContentType.TEXT_PLAIN));
        }
        for (File file : fileLists) {
            FileBody fileBody = new FileBody(file);
            meBuilder.addPart("files", fileBody);
        }
        HttpEntity reqEntity = meBuilder.build();
        httpPost.setEntity(reqEntity);
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 POST 请求（HTTP），JSON形式，包含消息头
     *
     * @param httpUrl
     * @param json    json对象
     * @return
     */
    public String doPostWithHeader(String httpUrl, Object json, Map<String, String> headers) {
        HttpPost httpPost = new HttpPost(httpUrl);
        CloseableHttpResponse response = null;

        try {
            httpPost.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");//解决中文乱码问题
            //stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);

            Iterator headerIterator = headers.entrySet().iterator();          //循环增加header
            while (headerIterator.hasNext()) {
                Map.Entry<String, String> elem = (Map.Entry<String, String>) headerIterator.next();
                httpPost.addHeader(elem.getKey(), elem.getValue());
            }
        } catch (Exception e) {
            //LOGGER.error("请求异常,httpUrl={},json={}", httpUrl, json, e);
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    //LOGGER.error("请求异常,httpUrl={},json={}", httpUrl, json, e);
                }
            }
        }
        return sendHttpPost(httpPost);
    }
}

